# coding: utf-8
#
# Copyright (c) Microsoft Corporation.  All rights reserved.
#
##
# Module containing classes to generate sh scripts used by installers
#
# Date:   2007-09-25 14:47:29
#

from shfunction import SHFunction
import scxutil

##
# Class for creating a script file.
#
class Script:
    ##
    # Ctor
    # \param[in] path Absolute path to generated script file.
    # \param[in] configuration Configuration map.
    #
    def __init__(self, path, configuration):
        self.path = path
        self.configuration = configuration

        # Get the path to 'sh' based on the platform
        self.header = [ scxutil.Get_sh_path(self) ]

        # Map of all shell global variables.
        self.variableMap = {
            'SCXHOME':                 '/opt/microsoft/scx',
            'SCX_TMP_PATH':            '/var/opt/microsoft/scx/tmp',
            'PAM_COMMENT':             '# The configuration of omi is generated by the scx installer.',
            'PAM_COMMENT_CLOSING':     '# End of section generated by the scx installer.',
            'PAM_SCX_COMMENT':         '# The configuration of scx is generated by the scx installer.',
            'PAM_CONF_FILE':       '/etc/pam.conf',
            'PAM_CONF_DIR':        '/etc/pam.d'
            }
        if self.configuration['pf'] == "SunOS":
            if self.configuration["pfminor"] <= 9:
                self.variableMap['pam_dir_passwd'] = 'auth requisite          pam_authtok_get.so.1\n' + \
                                                     'auth required           pam_dhkeys.so.1\n' + \
                                                     'auth required           pam_unix_auth.so.1\n' + \
                                                     'account requisite       pam_roles.so.1\n' + \
                                                     'account required        pam_unix_account.so.1'
            else:
                self.variableMap['pam_dir_passwd'] = 'auth requisite          pam_authtok_get.so.1\n' + \
                                                     'auth required           pam_dhkeys.so.1\n' + \
                                                     'auth required           pam_unix_cred.so.1\n' + \
                                                     'auth required           pam_unix_auth.so.1\n' + \
                                                     'account requisite       pam_roles.so.1\n' + \
                                                     'account required        pam_unix_account.so.1'
        elif self.configuration['pf'] == "Linux":
            if self.configuration['pfdistro'] == 'REDHAT':
                self.variableMap['pam_dir_passwd'] = 'auth       include      system-auth\n' + \
                                                     'account    required     pam_nologin.so\n' + \
                                                     'account    include      system-auth'
            elif self.configuration['pfdistro'] == 'SUSE':
                self.variableMap['pam_dir_passwd'] = 'auth     include        common-auth\n' + \
                                                     'auth     required       pam_nologin.so\n' + \
                                                     'account  include        common-account'
            elif self.configuration['pfdistro'] == 'ULINUX':
                self.variableMap['pam_dir_passwd_redhat'] = 'auth       include      system-auth\n' + \
                                                            'account    required     pam_nologin.so\n' + \
                                                            'account    include      system-auth'
                self.variableMap['pam_dir_passwd_suse'] = 'auth     include        common-auth\n' + \
                                                          'auth     required       pam_nologin.so\n' + \
                                                          'account  include        common-account'
                self.variableMap['pam_dir_passwd_ubuntu'] = 'auth     required       pam_env.so\n' + \
                                                            'auth     required       pam_unix.so nullok_secure\n' + \
                                                            'account  required       pam_unix.so\n' + \
                                                            'session  required       pam_limits.so'
            else:
                raise PlatformNotImplementedError(self.configuration['pfmajor'])
        elif self.configuration['pf'] == "HPUX":
            self.variableMap['pam_dir_passwd'] = 'auth required  libpam_hpsec.so.1\n' + \
                                                 'auth required  libpam_unix.so.1\n' + \
                                                 'account required       libpam_hpsec.so.1\n' + \
                                                 'account required       libpam_unix.so.1'
        elif self.configuration['pf'] == "AIX":
            self.variableMap['pam_dir_passwd'] = 'auth    required        /usr/lib/security/pam_aix\n' + \
                                                 'account required        /usr/lib/security/pam_aix'
        elif self.configuration['pf'] == "MacOS":
            self.variableMap['pam_dir_passwd'] = 'auth       required       pam_nologin.so\n' + \
                                                 'auth       sufficient     pam_securityserver.so\n' + \
                                                 'auth       sufficient     pam_unix.so\n' + \
                                                 'auth       required       pam_deny.so\n' + \
                                                 'account    required       pam_securityserver.so'
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])
        
        if self.configuration['pf'] != "Linux" or self.configuration['pfdistro'] != 'ULINUX':
            self.variableMap['pam_file_passwd'] = 'omi    ' + self.variableMap['pam_dir_passwd'].replace('\n', '\nomi    ')
        else:
            self.variableMap['pam_file_passwd_redhat'] = 'omi    ' + self.variableMap['pam_dir_passwd_redhat'].replace('\n', '\nomi    ')
            self.variableMap['pam_file_passwd_suse']   = 'omi    ' + self.variableMap['pam_dir_passwd_suse'].replace('\n', '\nomi    ')
            self.variableMap['pam_file_passwd_ubuntu'] = 'omi    ' + self.variableMap['pam_dir_passwd_ubuntu'].replace('\n', '\nomi    ')
   
        if self.configuration['pf'] == "MacOS":
            self.variableMap['SCXHOME'] = '/usr/libexec/microsoft/scx'

        self.functionList = []
        self.mainSection = ['#',
                            '# Main section',
                            '#']

    ##
    # Write line to main section of script.
    # \param[in] line Line to add to main section.
    #
    def WriteLn(self, line):
        self.mainSection = self.mainSection + [
            line
            ]
        
    ##
    # Inserts a call to a function in the main section.
    # The function definition is added to the functions section
    #
    def CallFunction(self, function, arguments = ''):
        self.mainSection = self.mainSection + [
            function.Name() + ' ' + arguments
            ]
        self.DefineFunction(function)

    ##
    # The function definition is added to the functions section
    # and a call to this function is returned.
    #
    def CallSubFunction(self, function, arguments = ''):
        self.DefineFunction(function)
        return function.Name() + ' ' + arguments

    ##
    # Inserts a function definition in the main section.
    # The function is not explicitly called.
    #
    def DefineFunction(self, function):
        for definedfunction in self.functionList:
            if function.Name() == definedfunction.Name():
                return
        self.functionList.append(function)

    ##
    # Writes the script to file.
    #
    def Generate(self):
        scriptfile = open(self.path, 'w')
        scxutil.ChMod(self.path, '0755')

        # Header information
        for line in self.header:
            scriptfile.write(line + '\n')
        scriptfile.write('\n')

        # Functions
        for function in self.functionList:
            scriptfile.write(function.Definition(self.variableMap))
            scriptfile.write('\n')
        scriptfile.write('\n')

        # Main section
        for line in self.mainSection:
            scriptfile.write(line + '\n')


    ##
    # Writes code to create soft link to directory containing sudo
    #
    def CreateSoftLinkToSudo(self):
        if self.configuration['pf'] == "SunOS":
            # Location of sudo is now version-dependent for Solaris
            if self.configuration['pfmajor'] > 5 or self.configuration['pfminor'] >= 11:
                self.sudoLocation = '/usr/bin'
            else:
                self.sudoLocation = '/opt/sfw/bin'
        else:
            self.sudoLocation = '/usr/bin'

        return SHFunction('create_softlink_to_sudo',
                          # Take care to not return a failing status if link exists
                          ['[ ! -L %(SCX_LOC)s ] && ln -s %(SUDO_DIR)s %(SCX_LOC)s || echo -n'],
                          {'SCX_LOC':   '/etc/opt/microsoft/scx/conf/sudodir',
                           'SUDO_DIR':  self.sudoLocation})


    ##
    # Writes the installinfo file containing creation date and version string.
    #
    def WriteInstallInfo(self):
        return SHFunction('write_install_info',
                          ['date +%%Y-%%m-%%dT%%T.0Z > %(INSTALL_INFO_FILE)s',
                           'echo %(VERSION_STRING)s >> %(INSTALL_INFO_FILE)s',
                           'return 0'
                           ],
                          {'INSTALL_INFO_FILE': '/etc/opt/microsoft/scx/conf/installinfo.txt',
                           'VERSION_STRING': self.configuration['version'] + '-' + self.configuration['release']})

    ##
    # Generates the ssl certificate.
    #
    def GenerateCertificate(self):
        varmap = {'SSL_DIR':           '/etc/opt/microsoft/scx/ssl',
                  'GENCERT_CERT_FILE': 'scx-host-`uname -n`.pem',
                  'SCX_SSL_CONFIG':    '/opt/microsoft/scx/bin/tools/scxsslconfig'}

        if self.configuration['pf'] == "MacOS":
            varmap['SCX_SSL_CONFIG'] = '/usr/libexec/microsoft/scx/bin/tools/scxsslconfig'

        body = [
            'if [ ! \"%(SSL_DIR)s\" = \"\" ] && [ -d %(SSL_DIR)s ]; then'
            ]

        # TODO: Shouldn't this test for solaris or something?
        if self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] <= 9:
            body = body + [
                ' LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib',
                ' export LD_LIBRARY_PATH'
                ]

        body = body + [
            '  if [ -f %(SSL_DIR)s/scx-seclevel1-key.pem ] && [ ! -f %(SSL_DIR)s/scx-key.pem ]; then',
            '    mv -f %(SSL_DIR)s/scx-seclevel1-key.pem %(SSL_DIR)s/scx-key.pem',
            '  fi',
            '  if [ -f %(SSL_DIR)s/scx-seclevel1.pem ] && [ ! -f %(SSL_DIR)s/scx.pem ]; then',
            '    mv -f %(SSL_DIR)s/scx-seclevel1.pem %(SSL_DIR)s/scx-host-`hostname`.pem',
            '    ln -s -f %(SSL_DIR)s/scx-host-`hostname`.pem %(SSL_DIR)s/scx.pem',
            '  fi',
            '  ( set +e; [ -f /etc/profile ] && . /etc/profile; set -e; %(SCX_SSL_CONFIG)s )',
            '  if [ $? -ne 0 ]; then',
            '    exit 1', # No need to print reason since SSL tool does that.
            '  fi',
            'else',
            '  # %(SSL_DIR)s : directory does not exist',
            '  exit 1',
            'fi',
            'return 0'
            ]
        
        return SHFunction('generate_certificate', body, varmap)

    ##
    # Decides on what pam configuration should be used
    # based on sshd configuration found in pam.conf file
    #
    def GetNewPAMConfig_file(self):
        body = [
            '#',
            '# Get configuration for sshd, service modules types auth and account',
            '#',
            'sshd_conf=`egrep \"^[# ]*sshd[ \t]+(auth|account)\" %(PAM_CONF_FILE)s`',
            'if [ $? -ne 0 ]; then',
            '  # No match found',
            '  # sshd not explicitly configured.',
            '  # Check to see if \"other\" is configured',
            '  other_conf=`egrep \"^[# ]*other[ \t]+(auth|account)\" %(PAM_CONF_FILE)s`',
            '  if [ $? -eq 0 ]; then',
            '    # \"other\" was found - use that (do not write any sort of new PAM configuraton)',
            '    return 0',
            '  fi',
            '  # Use passwd',
            ]
        
        if self.configuration['pf'] != "Linux" or self.configuration['pfdistro'] != 'ULINUX':
            body += [ '  sshd_conf=`echo \"%(pam_file_passwd)s\"`' ]
        else:
            body += [ 
                ' if [ -e \"/etc/debian_version\" ]; then',
                '   sshd_conf=`echo \"%(pam_file_passwd_ubuntu)s\"`',
                ' elif [ ! -e \"/etc/sysconfig/networking\" ] && [ ! -e\"/etc/sysconfig/network-scripts\"]; then',
                '   sshd_conf=`echo \"%(pam_file_passwd_suse)s\"` ]',
                ' else ' 
                '   sshd_conf=`echo \"%(pam_file_passwd_redhat)s\"`',
                ' fi '
                ]

        body += [
            'fi',
            '',
            '#',
            '# Substitute sshd with omi.',
            '#',
            'omi_conf=`echo \"$sshd_conf\" | sed \"s/sshd/omi/g\"`',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t parse %(PAM_CONF_FILE)s\"',
            '  return 1',
            'fi'
            ]
        return SHFunction('get_new_pam_config_file', body)
        
    ##
    # Decides on what pam configuration should be used
    # based on sshd configuration found in pam.d directory
    #
    def GetNewPAMConfig_dir(self):
        body = [
            '#',
            '# Get configuration for sshd, service modules types auth and account',
            '#',
            'sshd_conf=`egrep \"(auth|account)\" %(PAM_CONF_DIR)s/sshd 2> /dev/null`',
            'if [ $? -ne 0 ]; then',
            '  # No match found',
            '  # sshd not explicitly configured.',
            '  # Use passwd'
            ]

        if self.configuration['pf'] != "Linux" or self.configuration['pfdistro'] != 'ULINUX':
            body += [ '  sshd_conf=`echo \"%(pam_dir_passwd)s\"`' ]
        else:
            body += [
               ' if [ -e \"/etc/debian_version\" ]; then',
               '   sshd_conf=`echo \"%(pam_dir_passwd_ubuntu)s\"`',
               ' elif [ ! -e \"/etc/sysconfig/networking\" ] && [ ! -e\"/etc/sysconfig/network-scripts\"]; then',
               '   sshd_conf=`echo \"%(pam_dir_passwd_suse)s\"` ]',
               ' else '
               '   sshd_conf=`echo \"%(pam_dir_passwd_redhat)s\"`',
               ' fi '
               ]

        body += [
            'fi',
            '',
            'omi_conf=$sshd_conf'
            ]
                                                   
        return SHFunction('get_new_pam_config_dir', body)
        
    ##
    # Configure PAM in /etc/pam.conf
    #
    def ConfigurePAM_file(self):
        body = [
            '#',
            '# First check if omi is already configured in pam.conf',
            '#',
            'grep -s \"^[# ]*omi\" %(PAM_CONF_FILE)s > /dev/null 2>&1',
            'if [ $? -eq 0 ]; then',
            '  # Match found',
            '  # Looks like omi is already configured',
            '  echo \"omi already configured\"',
            '  return 0',
            'fi',
            '',
            self.CallSubFunction(self.GetNewPAMConfig_file()),
            '',
            '#',
            '# Only update pam.conf if we are returning some new configuration',
            'if [ \"$omi_conf\" ]; then',
            '  # Write the final configuration to pam.conf',
            '  #',
            '  # copy file first and modify this copy, so in case of low disk space we preserve the original file',
            '  cp %(PAM_CONF_FILE)s %(PAM_CONF_FILE)s.scx-copy && echo \"%(PAM_COMMENT)s\n$omi_conf\n%(PAM_COMMENT_CLOSING)s\n\" >> %(PAM_CONF_FILE)s.scx-copy',
            '  if [ $? -ne 0 ]; then',
            '    echo \"can\'t update file %(PAM_CONF_FILE)s.scx-copy\"',
            '    rm -f %(PAM_CONF_FILE)s.scx-copy',
            '    return 1',
            '  fi',
            '  # verify that complete file was written ',
            '  grep "%(PAM_COMMENT_CLOSING)s" %(PAM_CONF_FILE)s.scx-copy > /dev/null 2>&1',
            '  if [ $? -ne 0 ]; then',
            '    echo \"can\'t update file %(PAM_CONF_FILE)s.scx-copy\"',
            '    rm -f %(PAM_CONF_FILE)s.scx-copy',
            '    return 1',
            '  fi',
            '  # use move to substitute original file with verified copy',
            '  mv %(PAM_CONF_FILE)s.scx-copy %(PAM_CONF_FILE)s',
            '  if [ $? -ne 0 ]; then',
            '    echo \"can\'t replace %(PAM_CONF_FILE)s\"',
            '    return 1',
            '  fi',
            'fi'
            ]
        return SHFunction('configure_pam_file', body)

    ##
    # Configure PAM in /etc/pam.d
    #
    def ConfigurePAM_dir(self):
        body = [
            '#',
            '# First check if omi is already configured',
            '#',
            'if [ -f %(PAM_CONF_DIR)s/omi ]; then',
            '  # Match found',
            '  # Looks like omi is already configured',
            '  echo \"omi already configured\"',
            '  return 0',
            'fi',
            '',
            self.CallSubFunction(self.GetNewPAMConfig_dir()),
            'echo \"#%%PAM-1.0\n%(PAM_COMMENT)s\n$omi_conf\" > %(PAM_CONF_DIR)s/omi',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t create %(PAM_CONF_DIR)s/omi\"',
            '  return 1',
            'fi'
            ]
        return SHFunction('configure_pam_dir', body)

    ##
    # Configures PAM (Either /etc/pam.conf or /etc/pam.d)
    #
    def ConfigurePAM(self):
        body = ['#',
                '# Check if pam is configured with single',
                '# configuration file or with configuration',
                '# directory.',
                '#',
                'if [ -s %(PAM_CONF_FILE)s ]; then',
                '  ' + self.CallSubFunction(self.ConfigurePAM_file()),
                'elif [ -d %(PAM_CONF_DIR)s ]; then',
                '  ' + self.CallSubFunction(self.ConfigurePAM_dir()),
                'else',
                '  # No pam configuration.',
                '  echo \"PAM does not seem to be configured.\"',
                '  echo \"Checked both %(PAM_CONF_FILE)s and %(PAM_CONF_DIR)s.\"',
                '  return 1',
                'fi',
                'return 0'
                ]
        return SHFunction('configure_pam', body)

    ##
    # Determines the current SCX PAM configuration
    # from a pam.conf file.
    #
    def GetCurrentPAMConfig_file(self):
        body = [
            'omi_current_conf=`grep \"^[#\t]*omi\" %(PAM_CONF_FILE)s`',
            ]
        return SHFunction('get_current_pam_config_file', body)

    ##
    # Determines the current SCX PAM configuration
    # from a pam.conf file.
    #
    def GetCurrentPAMConfig_dir(self):
        body = [
            'omi_current_conf=`cat %(PAM_CONF_DIR)s/omi | grep -v \"#%%PAM-1.0\" | grep -v \"%(PAM_COMMENT)s\"`',
            ]
        return SHFunction('get_current_pam_config_dir', body)

    ##
    # Remove scx configuration from a pam.conf file
    #
    def UnconfigurePAM_file(self):
        body = [
            '# Configured with single file',
            '']
        
        # For SunOS we want to be a little smarter than just removing the file
        # since on uninstall for solaris we don't know if it is part of an
        # upgrade. So we only want to remove the configuration if a clean
        # installation would result in the same configuration as we have now.
        if self.configuration['pf'] == "SunOS":
            body.extend([
                self.CallSubFunction(self.GetNewPAMConfig_file()), # The result will be available in the $omi_conf variable
                self.CallSubFunction(self.GetCurrentPAMConfig_file()), # The result will be available in the $omi_current_conf variable
                'if [ \"$omi_conf\" != \"$omi_current_conf\" ]; then',
                '  # It looks like the configuration has been changed since',
                '  # installation or at least would change if we did a reinstall',
                '  # Safest to leave the configuration as is.',
                '  return 0',
                'fi'
                ])
        body.extend([
            '#',
            '# Get all lines except omi configuration',
            '#',
            'pam_configuration=`grep -v \"^[#\t]*omi\" %(PAM_CONF_FILE)s | grep -v \"%(PAM_COMMENT)s\" | grep -v \"%(PAM_COMMENT_CLOSING)s\"`',
            'if [ $? -ne 0 ]; then',
            '  # omi not configured in PAM',
            '  return 0',
            'fi',
            '#',
            '# Write it back (to the copy first)',
            '#',
            'cp -p %(PAM_CONF_FILE)s %(PAM_CONF_FILE)s.tmp',
            'echo \"$pam_configuration\" > %(PAM_CONF_FILE)s.tmp',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t write to %(PAM_CONF_FILE)s.tmp\"',
            '  return 1',
            'fi',
            'mv %(PAM_CONF_FILE)s.tmp %(PAM_CONF_FILE)s',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t replace %(PAM_CONF_FILE)s\"',
            '  return 1',
            'fi'
            ])
        return SHFunction('unconfigure_pam_file', body)

    ##
    # Remove scx configuration from a pam.d directory
    #
    def UnconfigurePAM_dir(self):
        body = [
            '# Configured with directory',
            'if [ -f %(PAM_CONF_DIR)s/omi ]; then'
            ]

        # For SunOS we want to be a little smarter than just removing the file
        # since on uninstall for solaris we don't know if it is part of an
        # upgrade. So we only want to remove the configuration if a clean
        # installation would result in the same configuration as we have now.
        if self.configuration['pf'] == "SunOS":
            body.extend([
                self.CallSubFunction(self.GetNewPAMConfig_dir()), # The result will be available in the $omi_conf variable
                self.CallSubFunction(self.GetCurrentPAMConfig_dir()), # The result will be available in the $omi_current_conf variable
                'if [ \"$omi_conf\" != \"$omi_current_conf\" ]; then',
                '  # It looks like the configuration has been changed since',
                '  # installation or at least would change if we did a reinstall',
                '  # Safest to leave the configuration as is.',
                '  return 0',
                'fi'
                ])

        body.extend([
            '  rm -f %(PAM_CONF_DIR)s/omi',
            '  return 0',
            'fi'
            ])
        return SHFunction('unconfigure_pam_dir', body)

    ##
    # Removes scx configuration from PAM
    #
    def UnconfigurePAM(self):
        body = [
            '#',
            '# Check if pam is configured with single',
            '# configuration file or with configuration',
            '# directory.',
            '#',
            'if [ -s %(PAM_CONF_FILE)s ]; then',
            '  ' + self.CallSubFunction(self.UnconfigurePAM_file()),
            'elif [ -d %(PAM_CONF_DIR)s ]; then',
            '  ' + self.CallSubFunction(self.UnconfigurePAM_dir()),
            'fi',
            'return 0'
            ]
        return SHFunction('unconfigure_pam', body)

    ##
    # Remove scx configuration from a pam.conf file
    # (This removes SCX configuration, not OMI configuration)
    #
    def UnconfigureScxPAM_file(self):
        body = [
            '# Configured with single file',
            '',
            '#',
            '# Get all lines except scx configuration',
            '#',
            'pam_configuration=`grep -v \"^[#\t]*scx\" %(PAM_CONF_FILE)s | grep -v \"%(PAM_SCX_COMMENT)s\" | grep -v \"%(PAM_COMMENT_CLOSING)s\"`',
            'if [ $? -ne 0 ]; then',
            '  # scx not configured in PAM',
            '  return 0',
            'fi',
            '#',
            '# Write it back (to the copy first)',
            '#',
            'cp -p %(PAM_CONF_FILE)s %(PAM_CONF_FILE)s.tmp',
            'echo \"$pam_configuration\" > %(PAM_CONF_FILE)s.tmp',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t write to %(PAM_CONF_FILE)s.tmp\"',
            '  return 1',
            'fi',
            'mv %(PAM_CONF_FILE)s.tmp %(PAM_CONF_FILE)s',
            'if [ $? -ne 0 ]; then',
            '  echo \"can\'t replace %(PAM_CONF_FILE)s\"',
            '  return 1',
            'fi'
            ]
        return SHFunction('unconfigure_scx_pam_file', body)

    ##
    # Remove scx configuration from a pam.d directory
    # (This removes SCX configuration, not OMI configuration)
    #
    def UnconfigureScxPAM_dir(self):
        body = [
            '# Configured with directory',
            'if [ -f %(PAM_CONF_DIR)s/scx ]; then'
            '  rm -f %(PAM_CONF_DIR)s/scx',
            '  return 0',
            'fi'
            ]
        return SHFunction('unconfigure_scx_pam_dir', body)

    ##
    # Removes scx configuration from PAM
    # (This removes SCX configuration, not OMI configuration)
    #
    def UnconfigureScxPAM(self):
        body = [
            '#',
            '# Check if pam is configured with single',
            '# configuration file or with configuration',
            '# directory.',
            '#',
            'if [ -s %(PAM_CONF_FILE)s ]; then',
            '  ' + self.CallSubFunction(self.UnconfigureScxPAM_file()),
            'elif [ -d %(PAM_CONF_DIR)s ]; then',
            '  ' + self.CallSubFunction(self.UnconfigureScxPAM_dir()),
            'fi',
            'return 0'
            ]
        return SHFunction('unconfigure_scx_pam', body)

    ##
    # Verifies that proper version of SSL exists on this system
    #
    def VerifySSLVersion(self):
        if self.configuration['pfdistro'] == 'ULINUX':
            body = [
                "openssl version | awk \'{print $2}\' | grep -Eq '^0.9.8|^1.0.'",
                'if [ $? -ne 0 ]; then',
                "  echo 'Unsupported OpenSSL version - must be either 0.9.8* or 1.0.*.'",
                "  echo 'Installation cannot proceed.'",
                '  exit 1',
                'fi'
                ]
        else:
            body = ['return 0']

        return SHFunction('verify_ssl_version', body)

    ##
    # Links to proper version of SSL, based on what is installed on the system:
    #
    #	Version		Linked to
    #	 0.9.8		/opt/microsoft/scx/bin -> /opt/microsoft/scx/bin_openssl_0.9.8
    #			/opt/microsoft/scx/lib -> /opt/microsoft/scx/lib_openssl_0.9.8
    #
    #	 1.0.*		/opt/microsoft/scx/bin -> /opt/microsoft/scx/bin_openssl_1.0.0
    #			/opt/microsoft/scx/lib -> /opt/microsoft/scx/lib_openssl_0.0.0
    #
    def CreateLinksForProperSSLVersion(self):
        if self.configuration['pfdistro'] == 'ULINUX':
                # Make soft links to correct OpenSSL directory
            body = [
                "SSL_VERSION=`openssl version | awk '{print $2}'`",
                "case $SSL_VERSION in",
                "  0.9.8*)",
                "    (cd /opt/microsoft/scx; ln -s bin_openssl_0.9.8 bin; ln -s lib_openssl_0.9.8 lib)",
                ]

            if self.configuration['pfarch'] == "x86":
                body += [
                    "    LIB_DIR=/lib",
                    "    DIR_LIST=\"/lib/ /usr/lib/\""
                    ]
            else:
                body += [
                    "    LIB_DIR=/lib64",
                    "    DIR_LIST=\"/lib64/ /usr/lib64/\""
                    ]

            body += [
                "    # We stage (in /opt/microsoft/scx/lib_openssl_0.9.8) two soft links of interest:",
                "    #   libcrypto.so.0.9.8 and libssl.so.0.9.8",
                "    # These resolve to files in /usr/lib/libcrypto.so and /usr/lib/libssl.so",
                "    # (or /usr/lib64/libcrypto.so and /usr/lib64/libssl.so) respectively.",
                "    # On some systems (Oracle Enterprise Linux), they don't exist.  Recover here.",
                "    if [ ! -e /usr${LIB_DIR}/libcrypto.so -o ! -e /usr${LIB_DIR}/libssl.so ]; then",
                "      # We don't have the links we expected; thus, create a list of dirs",
                "      # and extensions and then start looking for our SSL libraries ...",
                "      LIBCRYPTO_FILE=",
                "      LIBSSL_FILE=",
                "      SSL_VERSION_SUBS=`echo ${SSL_VERSION} | awk -F - '{print $1}'`",
                "      EXT_LIST=\"${SSL_VERSION} `echo ${SSL_VERSION} | tr -d A-Za-z` ${SSL_VERSION_SUBS} `echo ${SSL_VERSION_SUBS} | tr -d A-Za-z` \"",
                "",
                "      for dir in ${DIR_LIST}; do",
                "        for ext in ${EXT_LIST}; do",
                "          echo Checking existence of ${dir}libssl.so.${ext} and ${dir}libcrypto.so.${ext} ...",
                "          if [ -e ${dir}libssl.so.${ext} -a -e ${dir}libcrypto.so.${ext} ]; then",
                "            LIBCRYPTO_FILE=${dir}libcrypto.so.${ext}",
                "            LIBSSL_FILE=${dir}libssl.so.${ext}",
                "            echo \"  Found $LIBSSL_FILE and $LIBCRYPTO_FILE ...\"",
                "            break",
                "          fi",
                "        done",
                "        [ -n \"$LIBCRYPTO_FILE\" -a -n \"$LIBSSL_FILE\" ] && break",
                "      done",
                "",
                "      if [ -z ${LIBCRYPTO_FILE} -o -z ${LIBSSL_FILE} ]; then",
                "        echo \"Unable to find file libssl.so.0.9.8? or libcrypto.ssl.0.9.8?\"",
                "        exit 1",
                "      fi",
                "      rm /opt/microsoft/scx/lib_openssl_0.9.8/libcrypto.so.0.9.8",
                "      rm /opt/microsoft/scx/lib_openssl_0.9.8/libssl.so.0.9.8",
                "      ln -s ${LIBCRYPTO_FILE} /opt/microsoft/scx/lib_openssl_0.9.8/libcrypto.so.0.9.8",
                "      ln -s ${LIBSSL_FILE} /opt/microsoft/scx/lib_openssl_0.9.8/libssl.so.0.9.8",
                "    fi",
                "    ;;",
                "  1.0.*)",
                "    (cd /opt/microsoft/scx; ln -s bin_openssl_1.0.0 bin; ln -s lib_openssl_1.0.0 lib)",
                "    ;;",
                "  *)",
                "    echo \"Unable to determine SSL version for: $SSL_VERSION\"",
                "    exit 1",
                "esac"
                ]
        else:
            body = ['return 0']

        return SHFunction('create_links_for_ssl_binaries', body)

    ##
    # Unlinks to proper version of SSL (undoes CreateLinksForProperSSLVersion)
    #
    def RemoveLinksForProperSSLVersion(self):
        if self.configuration['pfdistro'] == 'ULINUX':
            body = [
                'rm /opt/microsoft/scx/lib /opt/microsoft/scx/bin'
                ]
        else:
            body = ['return 0']

        return SHFunction('unlink_for_ssl_binaries', body)

    ##
    # Installs scx-cimd as a service using native service management.
    #
    def ConfigureOmiService(self):
        if self.configuration['pf'] == "SunOS":
            if self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] < 10:
                body = ['return 0']
            elif self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] == 10:
                body = ['svccfg import /var/svc/manifest/application/management/scx-cimd.xml']
            else:
                body = ['svcadm restart svc:/system/manifest-import']
        elif self.configuration['pf'] == "Linux":
                body = []
                if self.configuration['pfdistro'] == 'ULINUX':
                    body += ['if [ -x /usr/sbin/update-rc.d ]; then',
                             ' update-rc.d scx-cimd defaults > /dev/null',
                             'elif']
                else:
                    body += ['if']

                body += [' [ -x /usr/lib/lsb/install_initd ]; then',
                         '  /usr/lib/lsb/install_initd /etc/init.d/scx-cimd', 
                         'elif [ -x /sbin/chkconfig ]; then', 
                         ' chkconfig --add scx-cimd > /dev/null',
                         'else',
                         ' echo "Unrecognized Service Controller to configure OMI Service."',
                         ' exit 1',
                         'fi']    
            
        elif self.configuration['pf'] == "HPUX":
            body = ['return 0']
        elif self.configuration['pf'] == "AIX":
            body = ['mkssys -s scx-cimd' + \
                    ' -p %(SCXHOME)s/bin/omiserver' + \
                    ' -u root -S -n 15 -f 9 -G scx',
                    'grep scx-cimd /etc/inittab > /dev/null 2>&1',
                    'if [ $? -eq 0 ]; then',
                    'rmitab scx-cimd',
                    'fi',
                    'mkitab \'scx-cimd:2:once:/usr/bin/startsrc -s scx-cimd -e " LIBPATH=\\"\\" LD_LIBRARY_PATH=\\"\\" " > /dev/console 2>&1\' ']
        elif self.configuration['pf'] == "MacOS":
            body = ['return 0']

        return SHFunction('configure_omi_service', body)

    ##
    # Starts the scx-cimd service
    #
    def StartOmiService(self):
        if self.configuration['pf'] == "SunOS":
            if self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] < 10:
                body = ['/etc/init.d/scx-cimd start']
            else:
                # The Solaris manifest file now starts automatically.  This change
                # was made due to Solaris 11, where you must restart the
                # manifest-import service to import new manifests.
                #
                # Prior to this change, the service would be started with a command
                # like: svcadm enable svc:/application/management/scx-cimd'
                #
                # End result: Just wait for the service to actually start.  This
                # eliminates a potential timing window where OM can fail discovery
                # if the package install completes but the service does not start
                # quickly enough ...
                body = [self.CallSubFunction(self.WaitForService(),
                                             'svc:/application/management/scx-cimd')
                        ]
        elif self.configuration['pf'] == "Linux":
            if self.configuration['pfdistro'] == "SUSE" and self.configuration['pfmajor'] == 9:
                body = ['/etc/init.d/scx-cimd start']
            else:
                if self.configuration['pfdistro'] != "ULINUX":
                    body = ['service scx-cimd start']
                else:
                    body = [ 'if [ -x /usr/sbin/invoke-rc.d ]; then',
                                 ' invoke-rc.d scx-cimd start',
                             'elif [ -x /sbin/service ]; then',
                                 'service scx-cimd start',
                             'else',
                                 ' echo "Unrecognized Service Controller to start SCX Service"',
                                 ' exit 1', 
                             'fi']
        elif self.configuration['pf'] == "HPUX":
            body = ['/sbin/init.d/scx-cimd start']
        elif self.configuration['pf'] == "AIX":
            body = ['startsrc -s scx-cimd']
        elif self.configuration['pf'] == "MacOS":
            body = ['launchctl load -w /Library/LaunchDaemons/com.microsoft.scx-cimd.plist']
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])
        
        return SHFunction('start_omi_service', body)

    ##
    # Stops the scx-cimd service
    #
    def StopOmiService(self):
        if self.configuration['pf'] == "SunOS":
            if self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] < 10:
                body = ['/etc/init.d/scx-cimd stop']
            else:
                body = ['svcadm disable -s svc:/application/management/scx-cimd']
        elif self.configuration['pf'] == "Linux":
            if self.configuration['pfdistro'] == "SUSE" and self.configuration['pfmajor'] == 9:
                body = ['/etc/init.d/scx-cimd stop']
            else:
                if self.configuration['pfdistro'] != "ULINUX":
                    body = ['service scx-cimd stop']
                else:
                    body = ['if [ -x /usr/sbin/invoke-rc.d ]; then',
                                 ' invoke-rc.d scx-cimd stop',
                            'elif [ -x /sbin/service ]; then',
                                 ' service scx-cimd stop',
                            'else',
                                 ' echo "Unrecognized Service Controller to stop SCX Service."',
                                 ' exit 1', 
                            'fi']
        elif self.configuration['pf'] == "HPUX":
            body = ['/sbin/init.d/scx-cimd stop']
        elif self.configuration['pf'] == "AIX":
            body = ['stopsrc -c -s scx-cimd']
        elif self.configuration['pf'] == "MacOS":
            body = ['launchctl unload -w /Library/LaunchDaemons/com.microsoft.scx-cimd.plist']
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])

        return SHFunction('stop_omi_service', body)

    ##
    # Unregisters the scx-cimd service
    #
    def RemoveOmiService(self):
        if self.configuration['pf'] == "SunOS":
            if self.configuration['pfmajor'] == 5 and self.configuration['pfminor'] < 10:
                body = ['return 0']
            else:
                body = ['svccfg delete svc:/application/management/scx-cimd:default']
        elif self.configuration['pf'] == "Linux":
            body = []        
            if self.configuration['pfdistro'] == 'ULINUX':
                body += ['if [ -x /usr/sbin/update-rc.d ]; then',
                         ' update-rc.d scx-cimd defaults > /dev/null',
                         'elif']
            else:
                body += ['if']
                
            body += [' [ -x /usr/lib/lsb/install_initd ]; then',
                     '  /usr/lib/lsb/install_initd /etc/init.d/scx-cimd', 
                     'elif [ -x /sbin/chkconfig ]; then', 
                     ' chkconfig --del scx-cimd > /dev/null',
                     'else',
                     ' echo "Unrecognized Service Controller to unregister OMI Service."',
                     ' exit 1',
                     'fi']    

        elif self.configuration['pf'] == "AIX":
            body = ['rmssys -s scx-cimd',
                    'rmitab scx-cimd']
        elif self.configuration['pf'] == "HPUX":
            body = ['return 0']
        elif self.configuration['pf'] == "MacOS":
            body = ['return 0']
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])

        return SHFunction('unregister_omi_service', body)

    ##
    # Writes code to delete soft link to directory containing sudo
    #
    # Note that generated code will only delete the link if it's not
    # what we expect it to be for the platform.
    #
    def DeleteSoftLinkToSudo(self):
        if self.configuration['pf'] == "SunOS":
            # Location of sudo is now version-dependent for Solaris
            if self.configuration['pfmajor'] > 5 or self.configuration['pfminor'] >= 11:
                self.sudoLocation = '/usr/bin'
            else:
                self.sudoLocation = '/opt/sfw/bin'
        else:
            self.sudoLocation = '/usr/bin'

        return SHFunction('delete_softlink_to_sudo',
                          ['if [ -L %(SCX_LOC)s ]; then',
                           '   LINKED_DIR=`(cd %(SCX_LOC)s ; pwd -P)`',
                           '   [ x${LINKED_DIR} = x%(SUDO_DIR)s ] && rm %(SCX_LOC)s',
                           'fi'
                          ],
                          {'SCX_LOC':   '/etc/opt/microsoft/scx/conf/sudodir',
                           'SUDO_DIR':  self.sudoLocation})


    ##
    # If the platform does not support upgrade call this method to
    # remove all files that has been removed in this release
    #
    def RemoveDeletedFiles(self):
        body = [
            'rm -f %(SCXHOME)s/lib/libpegCLIClientLib.*',
            'rm -f %(SCXHOME)s/lib/libpegcql.*',
            'rm -Rf /var/opt/microsoft/scx/lib/repository/root#scx/classes'
            ]

        return SHFunction('remove_deleted_files', body)

    ##
    # Configures runas using sshd_config as template
    #
    def ConfigureRunas(self):
        varmap = {}
        varmap['RUNAS_CFG'] = '/etc/opt/microsoft/scx/conf/scxrunas.conf'

        body = [
            'if [ -s %(RUNAS_CFG)s ]; then',
            '  # File is not zero size',
            '  return 0',
            'fi',
            '/opt/microsoft/scx/bin/tools/scxadmin -config-reset RunAs AllowRoot > /dev/null 2>&1'
            ] 
            
        return SHFunction('configure_runas', body, varmap)

    ##
    # Helper shell function that verifies that a required patch is installed on SunOS.
    # It is successful if the the required patch is found, if a newer version of the 
    # same patch is found, or if a patch is found that obsoletes the required patch 
    # (or a newer version of it).
    #
    def VerifyPatchInstalled(self):
        body = [
           'patchadd -p | nawk \'BEGIN { code = 0 }',
           '        { split($2, a, "-"); if (a[1] == base && a[2] >= ver) code=1 }',
           '        { for (i = 4 ; i <= NF; ++i) { if ($i == "Requires:") break;',
           '                                       split($i, a, "-");',
           '                                       if (a[1] == base && a[2] >= ver) code=2 }',
           '                                    }',
           '        END { exit(code) }\' base=$1 ver=$2',
           'if [ $? -eq 0 ]; then',
           '  echo "Required patch $1-$2 was not found. Please install patch and try again.";',
           '  exit 1',
           'fi',
           'return 0'
           ]
        return SHFunction('verify_patch_installed', body)


    ##
    # Wait for service to start / come online
    #
    def WaitForService(self):
        if self.configuration["pf"] == "SunOS" and ((self.configuration["pfmajor"] == 5 and self.configuration["pfminor"] >= 10) or self.configuration["pfmajor"] > 5):
            body = [
                'set +e',
                'COUNT=0',
                'while [ $COUNT -lt 15 ]; do',
                '    echo "Waiting for service: $1 ..."',
                '    sleep 1',
                '    /usr/bin/svcs -H $1 2> /dev/null | grep -i online > /dev/null 2>&1',
                '    [ $? -eq 0 ] && break',
                '    COUNT=`expr $COUNT + 1`',
                'done',
                'return 0'
                ]
        else:
            body = ['return 0'];

        return SHFunction('wait_for_service', body)


    ##
    # Checks for additional dependencies that package format can not handle natively
    #
    def CheckAdditionalDeps(self):
        body = []
        if self.configuration['pf'] == "SunOS" and self.configuration['pfarch'] == "sparc":
            body = body + [
                'if [ `uname -p` != \"sparc\" ]; then',
                '  echo \"This package only supports sparc architecture.\"',
                '  exit 1',
                'fi'
                ]
            if self.configuration["pfmajor"] == 5 and self.configuration["pfminor"] == 9:
                # We need 112960-48 for bug ID 4974005 (PAM memory leak)
                body = body + [
                    self.CallSubFunction(self.VerifyPatchInstalled(), '112960 48')
                    ]
            elif self.configuration["pfmajor"] == 5 and self.configuration["pfminor"] == 10:
                body = body + [
                    self.CallSubFunction(self.VerifyPatchInstalled(), '117463 05')
                    ]
        elif self.configuration['pf'] == "SunOS" and self.configuration['pfarch'] == "x86" and self.configuration["pfminor"] < 11:
            body = body + [
                'if [ `uname -p` != \"i386\" ]; then',
                '  echo \"This package only supports x86 architecture.\"',
                '  exit 1',
                'fi',
                self.CallSubFunction(self.VerifyPatchInstalled(), '117464 04')
                ]
        elif self.configuration['pf'] == "SunOS" and self.configuration['pfarch'] == "x86" and self.configuration["pfminor"] >= 11:
            body = body + [
                'if [ `uname -p` != \"i386\" ]; then',
                '  echo \"This package only supports x86 architecture.\"',
                '  exit 1',
                'fi'
                ]

        if self.configuration['pf'] == "SunOS" and self.configuration["pfminor"] >= 11:
            # In Solaris 11, we need to check IPS dependencies.
            body = body + [
                'pkg list system/core-os > /dev/null 2>&1',
                'if [ $? -ne 0 ]; then',
                '  echo \"Dependency missing: IPS package system/core-os is not installed.\"',
                '  exit 1',
                'fi',
                'pkg list system/library > /dev/null 2>&1',
                'if [ $? -ne 0 ]; then',
                '  echo \"Dependency missing: IPS package system/library is not installed.\"',
                '  exit 1',
                'fi',
                'pkg list system/library/c++-runtime > /dev/null 2>&1',
                'if [ $? -ne 0 ]; then',
                '  echo \"Dependency missing: IPS package system/library/c++-runtime is not installed.\"',
                '  exit 1',
                'fi',
                'pkg list system/library/math > /dev/null 2>&1',
                'if [ $? -ne 0 ]; then',
                '  echo \"Dependency missing: IPS package system/library/math is not installed.\"',
                '  exit 1',
                'fi',
                'pkg list library/security/openssl > /dev/null 2>&1',
                'if [ $? -ne 0 ]; then',
                '  echo \"Dependency missing: IPS package library/security/openssl is not installed.\"',
                '  exit 1',
                'fi'
                ]

        body = body + [
            'return 0'
            ]

        return SHFunction('check_additional_deps', body)

    ##
    # Removes files that are left by the package format
    #
    def RemoveAdditionalFiles(self):
        return SHFunction('remove_additional_files',
                          ['rm -r %(SCX_TMP_PATH)s > /dev/null 2>&1',
                           'return 0'])

    ##
    # Removes a directory recursivly but leaves any non-empty directories (i.e. with files).
    #
    def RemoveEmptyDirectoryRecursive(self):
        return SHFunction('remove_empty_directory_recursive',
                          ['find $1 -type d | sort -r |',
                           'while read D',
                           'do',
                           '  ls -l $D | grep -q \'total 0\' && rmdir  $D 2>/dev/null',
                           'done'])

    ##
    # Creates the /usr/sbin/scxadmin link manually (used primarily on Solaris 5.10 and greater)
    #
    def CreateLink_usr_sbin_scxadmin(self):
	if self.configuration['pf'] == 'MacOS':
            return SHFunction('CreateLink_usr_sbin_scxadmin',
                              ['ln -s /usr/libexec/microsoft/scx/bin/tools/scxadmin /usr/sbin/scxadmin > /dev/null 2>&1'])
        else:
            return SHFunction('CreateLink_usr_sbin_scxadmin',
                              ['ln -s /opt/microsoft/scx/bin/tools/scxadmin /usr/sbin/scxadmin > /dev/null 2>&1'])

    ##
    # Removes the /usr/sbin/scxadmin link manually (used primarily on Solaris 5.10 and greater)
    #
    def RemoveLink_usr_sbin_scxadmin(self):
        return SHFunction('RemoveLink_usr_sbin_scxadmin',
                          ['rm /usr/sbin/scxadmin > /dev/null 2>&1'])

    ##
    # Backs up configuration file (argument 1) to another name so it will not be
    # overwritten by the installation.
    #
    def BackupConfigurationFile(self):
        if self.configuration['pf'] == "HPUX" or self.configuration['pf'] == 'MacOS':
            return SHFunction('backup_configuration_file', ['mv \"$1\" \"$1.swsave\" > /dev/null 2>&1'])
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])

    ##
    # Restores configuration file (argument 1) from backed up version
    #
    def RestoreConfigurationFile(self):
        if self.configuration['pf'] == "HPUX" or self.configuration['pf'] == 'MacOS':
            return SHFunction('restore_configuration_file', ['mv \"$1.swsave\" \"$1\"'])
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])
    
        
    ##
    # Installs a configuration file.
    # Does not install the file if it is there already.
    # On Solaris the file is copied to a special location for "safekeeping" as well.
    #
    def InstallConfigurationFile(self):
        if self.configuration['pf'] == "SunOS":
            return SHFunction(
                'install_configuration_file',
                [
                '# Skip /dev/null',
                '[ \"$1\" = /dev/null ] && return 0',
                '',
                '# savepath is where original configuration files are stored',
                '# for later comparison',
                'savepath=$PKGSAV/config$2',
                '# Find the directory part of the savepath',
                'dirname=`dirname $savepath` || return 1',
                '',
                '# If directory does not exist, create it.',
                'if [ ! -d $dirname ]; then',
                '  mkdir -p $dirname',
                'fi'
                '',
                '# If there is an old saved version of the configuration file then use it',
                'if [ -f \"$2.pkgsave\" ]; then',
                '  mv \"$2.pkgsave\" \"$2\" || return 1',
                '  cp $1 $savepath || return 1',
                'else',
                '  echo $2',
                '  cp $1 $2 || return 1',
                '  cp $1 $savepath || return 1',
                'fi',
                'return 0'
                ])
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])
        
    ##
    # Uninstalls a configuration file.
    # If the file has changes since intall time it is instead renamed
    # as *.pkgsave.
    #
    def UninstallConfigurationFile(self):
        if self.configuration['pf'] == "SunOS":
            return SHFunction(
                'uninstall_configuration_file',
                [
                '# savepath is where original configuration files are stored',
                '# for comparison',
                'savepath=$PKGSAV/config$1',
                '',
                '/usr/bin/diff $1 $savepath > /dev/null',
                'if [ $? -ne 0 ]; then',
                '  # The configuration file has changed since install time.',
                '  mv $1 $1.pkgsave',
                'else',
                '  echo $1',
                '  rm -f $1 || return 1',
                'fi',
                'rm -f $savepath',
                'return 0'
                ])
        else:
            raise PlatformNotImplementedError(self.configuration['pf'])
        
    # If there was an old version installed, maintain state of previous install from pre-install to post-install for data migration purposes
    def CreateConfBackupTemp(self):
        if self.configuration['pf'] == "SunOS":
            return SHFunction(
                'create_conf_temp',
                [
                'if [ -f /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup ]; then',
                '    cp /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp',
                'fi',
                # On SunOS, there is no upgrade feature and cimserver_current.conf gets renamed to cimserver_current.conf.pkgsave before install.
                'if [ -f /etc/opt/microsoft/scx/conf/cimserver_current.conf.pkgsave ]; then',
                '    cp /etc/opt/microsoft/scx/conf/cimserver_current.conf.pkgsave /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp',
                'fi'
                ])
        else:
            return SHFunction(
                'create_conf_temp',
                [
                'if [ -f /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup ]; then',
                '    cp /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp',
                'fi',
                'if [ -f /etc/opt/microsoft/scx/conf/cimserver_current.conf ]; then',
                '    cp /etc/opt/microsoft/scx/conf/cimserver_current.conf /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp',
                'fi'
                ])

    # We're done with these temporary files for maintaining state, remove them if they exist.
    def RemoveConfBackupTemp(self):
        return SHFunction(
            'remove_conf_temp',
            [
            'if [ -f /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp ]; then',
            '    rm /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp',
            'fi',
            'if [ -f /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp ]; then',
            '    rm /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp',
            'fi'
            ])

    def HandleConfigFiles(self):
        return SHFunction(
            'handle_config_files',
            [
            'if [ -f /etc/opt/microsoft/scx/conf/omiserver.conf.pkgsave ]; then',
                 # This happens on SunOS on upgrade if omiserver.conf was modified by user.  Keep their omiserver.conf.
            '    mv /etc/opt/microsoft/scx/conf/omiserver.conf.pkgsave /etc/opt/microsoft/scx/conf/omiserver.conf',
            'elif [ -f /etc/opt/microsoft/scx/conf/omiserver.conf -a -f /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp ]; then',
                 # Has the user modified their omiserver.conf file?  If so, leave it in place.  Otherwise, overwrite omiserver.conf with new version
            '    diff /etc/opt/microsoft/scx/conf/omiserver.conf /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup_tmp > /dev/null 2>&1',
            '    if [ $? -eq 0 ]; then',
            '        cp /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup /etc/opt/microsoft/scx/conf/omiserver.conf',
            '    fi',
            'elif [ ! -f /etc/opt/microsoft/scx/conf/omiserver.conf -a -f /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp ]; then',
                 # If we're upgrading from a pegasus version, write out the new omiserver.conf file, appending data from old pegasus config
            '    cp /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup /etc/opt/microsoft/scx/conf/omiserver.conf',
            '    echo `grep sslCipherSuite /etc/opt/microsoft/scx/conf/cimserver_current.conf_tmp` | sed "s@sslCipherSuite@sslciphersuite@" >> /etc/opt/microsoft/scx/conf/omiserver.conf',
            'else',
                 # Catch all case, just write out omiserver.conf
            '    cp /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup /etc/opt/microsoft/scx/conf/omiserver.conf',
            'fi',
            # Clean up old pegasus conf files if they exist
            'rm -f /etc/opt/microsoft/scx/conf/cimserver_current.conf* /etc/opt/microsoft/scx/conf/cimserver_planned.conf*'
            ])

    # On a clean uninstall, we want to remove omiserver.conf
    def RemoveConfigFiles(self):
        if self.configuration['pf'] == "SunOS":
            return SHFunction(
                'remove_config_files',
                [
                'if [ -f /etc/opt/microsoft/scx/conf/omiserver.conf -a -f /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup ]; then',
                     # On SunOS there is no upgrade.  We want to save omiserver.conf if it was modified.
                '    diff /etc/opt/microsoft/scx/conf/omiserver.conf /etc/opt/microsoft/scx/conf/.baseconf/omiserver.backup',
                '    if [ $? -eq 1 ]; then',
                '        mv /etc/opt/microsoft/scx/conf/omiserver.conf /etc/opt/microsoft/scx/conf/omiserver.conf.pkgsave 2> /dev/null',
                '    else',
                '        rm /etc/opt/microsoft/scx/conf/omiserver.conf 2> /dev/null',
                '    fi',
                'else',
                '    rm /etc/opt/microsoft/scx/conf/omiserver.conf 2> /dev/null',
                'fi'
                ])
        else:
            return SHFunction(
                'remove_config_files',
                [
                'rm /etc/opt/microsoft/scx/conf/omiserver.conf 2> /dev/null'
                ])
